package com.aisino.inveli.vinda.service.impl;

import com.aisino.inveli.vinda.entity.GoodsDetail;
import com.aisino.inveli.vinda.entity.GoodsList;
import com.aisino.inveli.vinda.service.GoodsService;
import com.aisino.inveli.vinda.utils.MathUtil;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author leifeng
 * @Date 2017-11-15
 **/
@Service
public class GoodsServiceImpl implements GoodsService {

    @Override
    public GoodsList parseGoodsByFile(String selectPath) {
        GoodsList fsg = new GoodsList();
        List<GoodsDetail> allList = new ArrayList<>();
        File f = new File(selectPath);
        if (!f.exists()) {
            return null;
        }
        try {
            FileInputStream in = new FileInputStream(f);
            // 指定读取文件时以UTF-8的格式读取
            BufferedReader br = new BufferedReader(new InputStreamReader(in,
                    "GBK"));
            String line ;
            String key = "SJJK0101";
            //读取第一行---eg:SJJK0101~~VAT发票数据传入~~Generate by HAND
            line = br.readLine();
            if (line == null || !line.contains(key)) {
                return null;
            }
            //读取第二行---eg:833036~~19~~1203~~深圳市鹏腾实业有限公司~~440306766388256
            //~~深圳市宝安区6区畜牧局宿舍楼下10、12号 ~~中国建设银行深圳市宝安支行 44201538900052500000~~ ~~~~~~
            line = br.readLine();
            if (line == null || line.trim().length() == 0) {
                return null;
            }
            fsg.setHeaderStr(line);
            //继续读往下的商品内容信息
            while ((line = br.readLine()) != null) {
                if (line.trim().length() == 0) {
                    continue;
                }
                GoodsDetail fss = changeGoodsList(line);
                if (fss != null) {
                    allList.add(fss);
                }
            }
            //全部商品集合
            fsg.setAllList(allList);
            br.close();
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fsg;
    }

    @Override
    public GoodsList calculateGoodsList(GoodsList goodsList) {
        //商品总金额
        BigDecimal to = getTotalMon(goodsList.getAllList());
        //商品不含税总金额
        BigDecimal toNoRateMon = getTotalNoRateMon(goodsList.getAllList());
        //商品退货总金额
        BigDecimal toZK = getTotalZk(goodsList.getAllList());
        //oracle不含税金额
        goodsList.setOracleTotalNoRateMon(toNoRateMon.toString());
        //oracle金额
        goodsList.setOracleTotalMon(to.subtract(toZK).doubleValue());
        goodsList.setZk(toZK.doubleValue());
        return goodsList;
    }

    @Override
    public GoodsList mergeGoods(GoodsList goodsList) {
        List<GoodsDetail> list = goodsList.getAllList();
        //使用name+type作为key进行商品筛选
        HashMap<String, GoodsDetail> map = new HashMap<>(16);
        // 存储同类项
        List<GoodsDetail> del = new ArrayList<>();
        // 合并项
        List<GoodsDetail> merge = new ArrayList<>();
        for (GoodsDetail fsg : list) {
            String name = fsg.getName();
            String type = fsg.getType();
            String key = name + type;
            if (map.get(key) == null) {
                //第一次出现此商品
                map.put(key, fsg);
            } else {
                //再次出现则需进行合并
                GoodsDetail newGs = fsg;
                //获取以前曾经遍历的商品信息
                GoodsDetail temp = map.get(key);
                //以往遍历商品金额
                String tempMonStr = temp.getMon();
                // 记录金额
                double tempMon = 0.0;
                if (tempMonStr != null) {
                    if (tempMonStr.trim().length() == 0) {
                        tempMon = 0.0;
                    } else{
                        tempMon = Double.parseDouble(tempMonStr);
                    }
                }
                //当前商品金额
                String sfgMonStr = fsg.getMon();
                double sfgMon = 0.0;
                if (sfgMonStr != null) {
                    if (sfgMonStr.trim().length() == 0) {
                        sfgMon = 0.0;
                    } else{
                        sfgMon = Double.parseDouble(sfgMonStr);
                    }
                }
                //以往商品數量
                String tempNumStr = temp.getNum();
                double tempNum = 0.0;
                if (tempNumStr != null) {
                    if (tempNumStr.trim().length() == 0) {
                        tempNum = 0.0;
                    } else {
                        tempNum = Double.parseDouble(tempNumStr);
                    }
                }
                //当前商品数量
                String sfgNumStr = fsg.getNum();
                double sfgNum = 0.0;
                if (sfgNumStr != null) {
                    if (sfgNumStr.trim().length() == 0) {
                        sfgNum = 0.0;
                    } else {
                        sfgNum = Double.parseDouble(sfgNumStr);
                    }
                }
                //以往商品不含税金额
                String tempNoRateMonStr = temp.getNoRateMon();
                BigDecimal tempNoRateMon = new BigDecimal(0);
                if (tempNoRateMonStr != null) {
                    if (tempNoRateMonStr.trim().length() == 0) {
                        tempNoRateMon = new BigDecimal(0);
                    } else {
                        tempNoRateMon = new BigDecimal(tempNoRateMonStr);
                    }
                }
                //当前商品不含税金额
                String sfgNoRateMonStr = fsg.getNoRateMon();
                BigDecimal sfgNoRateMon =new BigDecimal(0);
                if (sfgNoRateMonStr != null) {
                    if (sfgNoRateMonStr.trim().length() == 0) {
                        sfgNoRateMon = new BigDecimal(0);
                    } else {
                        sfgNoRateMon =new BigDecimal(sfgNoRateMonStr);
                    }
                }
                //以往商品折扣
                String tempDisMonStr = temp.getDisMon();
                BigDecimal tempDisMon = new BigDecimal(0);
                if (tempDisMonStr != null) {
                    if (tempDisMonStr.trim().length() == 0) {
                        tempDisMon = new BigDecimal(0);
                    } else {
                        tempDisMon = new BigDecimal(tempDisMonStr);
                    }
                }
                //当前商品折扣
                String sfgDisMonStr = fsg.getDisMon();
                BigDecimal sfgDisMon =new BigDecimal(0);
                if (sfgDisMonStr != null) {
                    if (sfgDisMonStr.trim().length() == 0) {
                        sfgDisMon = new BigDecimal(0);
                    } else {
                        sfgDisMon =new BigDecimal(sfgDisMonStr);
                    }
                }
                //当前商品、以往商品不含税金额进行保留2位小数操作
                sfgNoRateMon = MathUtil.getTwoPointBig(sfgNoRateMon);
                tempNoRateMon = MathUtil.getTwoPointBig(tempNoRateMon);
                //折扣相加
                newGs.setDisMon(sfgDisMon.add(tempDisMon).toString());
                //金额相加
                newGs.setMon((tempMon + sfgMon) + "");
                //数量相加
                newGs.setNum((tempNum + sfgNum) + "");
                //不含税金额相加
                newGs.setNoRateMon(MathUtil.getTwoPointBig(tempNoRateMon.add(sfgNoRateMon)).toString());
                //重新加入map集合
                map.put(key, newGs);
                //将以往商品信息记录、当前商品信息记录删除
                del.add(temp);
                del.add(fsg);
                if (tempNum + sfgNum == 0) {
                    newGs.setNum("");
                }
                //删除旧记录旧记录
                merge.remove(temp);
                if (tempMon + sfgMon != 0) {
                    merge.add(newGs);
                }
            }
        }
        list.removeAll(del);
        list.addAll(merge);
        goodsList.setAllList(list);
        return goodsList;
    }

    @Override
    public GoodsList changeFourList(GoodsList goodsList) {
        //正数List
        List<GoodsDetail> zsl = new ArrayList<>();
        //负数List
        List<GoodsDetail> fsl = new ArrayList<>();
        //包含超市奖励List
        List<GoodsDetail> csjll = new ArrayList<>();
        //金额调整List
        List<GoodsDetail> jetzl = new ArrayList<>();
        List<GoodsDetail> allList = goodsList.getAllList();
        for (GoodsDetail fss : allList) {
            if (fss.getName().indexOf("超市奖励") != -1) {
                // 超市奖励
                csjll.add(fss);
                continue;
            }
            if (fss.getName().indexOf("金额调整") != -1) {
                // 金额调整
                jetzl.add(fss);
                continue;
            }
            //获取当前商品金额
            String monStr = fss.getMon();
            if (monStr == null || monStr.length() == 0) {
                continue;
            }
            float mon = Float.parseFloat(monStr);
            if (mon < 0) {
                // 负数
                fss.setMon(new BigDecimal(fss.getMon()).subtract(new BigDecimal(fss.getDisMon())).toString());
                fsl.add(fss);
            }
            if (mon > 0) {
                // 正数
                String numStr = fss.getNum();
                float num = 0.0f;
                if (numStr == null || numStr.trim().length() == 0) {
                    fss.setNum("");
                    fss.setFlag(true);
                }
                else {
                    num = Float.parseFloat(numStr);
                }
                float price;
                if (num <= 0) {
                    // 數量小於0標紅
                    fss.setNum("");
                    fss.setPrice(0.00f);
                    fss.setFlag(true);
                } else {
                    price = mon / num;
                    if (price <= 10) {
                        // 单价《=10标红
                        fss.setPrice(price);
                        fss.setFlag(true);
                    } else {
                        fss.setPrice(price);
                        fss.setFlag(false);
                    }
                }
                zsl.add(fss);
            }
            // ==0不要
        }
        goodsList.setListCSZJ(csjll);
        goodsList.setListJETZ(jetzl);
        goodsList.setListZS(zsl);
        goodsList.setListFS(fsl);
        return goodsList;
    }

    @Override
    public GoodsList mainChange(Double rate, Boolean sup, Boolean mon, GoodsList goodsList) {
        List<GoodsDetail> resultFS = new ArrayList<>();
        List<GoodsDetail> resultZS = new ArrayList<>();
        List<GoodsDetail> disList = new ArrayList<>();
        // 没勾选的超市奖励
        if (!sup) {
            if (goodsList.getListCSZJ() != null && goodsList.getListCSZJ().size() != 0){
                resultFS.addAll(goodsList.getListCSZJ());
            }
        } else {
            if (goodsList.getListCSZJ() != null && goodsList.getListCSZJ().size() != 0){
                disList.addAll(goodsList.getListCSZJ());
            }
        }
        // 没勾选的金额调整
        if (!mon) {
            if (goodsList.getListJETZ() != null && goodsList.getListJETZ().size() != 0){
                resultFS.addAll(goodsList.getListJETZ());
            }
        } else {
            if (goodsList.getListJETZ() != null && goodsList.getListJETZ().size() != 0){
                disList.addAll(goodsList.getListJETZ());
            }
        }
        // 本身就是负数的商品
        if (goodsList.getListFS() != null && goodsList.getListFS().size() != 0){
            resultFS.addAll(goodsList.getListFS());
        }
        // 本身正数
        if (goodsList.getListZS() != null && goodsList.getListZS().size() != 0){
            resultZS.addAll(goodsList.getListZS());
        }
        // 设置折扣
        goodsList.setFsTotal(getTotalMon(resultFS).doubleValue());
        goodsList.setZsTotal(getTotalMon(goodsList.getListZS()).doubleValue());
        goodsList.setDisTotal(getTotalMon(disList).abs().doubleValue() + goodsList.getZk());
        goodsList.setDistotalStr(getTotalMon(disList).abs().add(new BigDecimal(goodsList.getZk())).setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        BigDecimal temp = new BigDecimal(goodsList.getDisTotal());
        //计算不含税金额
        temp = temp.divide(new BigDecimal(rate),2,BigDecimal.ROUND_HALF_UP);
        goodsList.setTotalNoRateZK(temp.toString());
        // 折扣率 = 折扣商品金额/（正数商品金额+调整金额）
        // 不对其进行四舍五入
        Double zkDiscount = Math.abs(Double.valueOf(goodsList.getDisTotal())
                / goodsList.getZsTotal());
        goodsList.setDiscount(zkDiscount);
        goodsList.setResultFS(resultFS);
        goodsList.setResultZS(resultZS);
        return goodsList;
    }

    /**
     * 调整正数商品
     * @param goodsList
     * @return
     */
    @Override
    public GoodsList adjustZsGoodsList(GoodsList goodsList) {
        //总折扣金额
        BigDecimal tdis = new BigDecimal(0);
        //总不含税折扣金额
        BigDecimal tNoRateDis = new BigDecimal(0);
        //获取折扣率
        BigDecimal dc = new BigDecimal(goodsList.getDiscount());
        for (int i = 0; i < goodsList.getResultZS().size(); i++) {
            GoodsDetail goodsDetail = goodsList.getResultZS().get(i);
            BigDecimal dis ;
            // 当前商品金额
            BigDecimal oldMon = new BigDecimal(goodsDetail.getMon());
            if(dc.compareTo(new BigDecimal(0)) == 0){
                //如果当前的商品在导入之前就存在折扣金额，则直接将折扣金额写入
                if(!"0".equals(goodsDetail.getDisMon())){
                    dis =new BigDecimal(goodsDetail.getDisMon()).setScale(2, BigDecimal.ROUND_HALF_UP);;
                }else{
                    //求折扣金额
                    dis = oldMon.multiply(dc).setScale(2, BigDecimal.ROUND_HALF_UP);
                }
            }else{
                //重新计算折扣，利用新折扣计算折扣金额
                Double newDc = Math.abs(Double.valueOf(goodsList.getDisTotal()))
                        / goodsList.getZsTotal();
                dc = new BigDecimal(newDc);
                dis = oldMon.multiply(dc);
            }
            //不含税折扣金额
            BigDecimal noRateDis = new BigDecimal(goodsDetail.getNoRateMon()).multiply(dc);
            //四舍五入
            dis = MathUtil.getTwoPointBig(dis);
            //四舍五入
            noRateDis = MathUtil.getTwoPointBig(noRateDis);
            goodsDetail.setDisMon(dis.toString());
            //set回对象的不含税折扣金额
            goodsDetail.setNoRateDisMon(noRateDis.toString());
            //累加 求和
            tdis = tdis.add(dis);
            //累加求和
            tNoRateDis = tNoRateDis.add(noRateDis);
        }
        goodsList = amendment(goodsList,tdis.doubleValue());
        return goodsList;
    }

    @Override
    public String countTotalAmount(List<GoodsDetail> resultZS) {
        BigDecimal amount = new BigDecimal(0);
        for (int i = 0; i < resultZS.size(); i++) {
            GoodsDetail goodsDetail = resultZS.get(i);
            String mon = goodsDetail.getMon()==null?"0.00":goodsDetail.getMon();
            String adjustMon = goodsDetail.getAdjustMon() == null?"0.00":goodsDetail.getAdjustMon();
            amount = amount.add(new BigDecimal(mon)).add(new BigDecimal(adjustMon));
        }
        return amount.setScale(2,BigDecimal.ROUND_HALF_UP).toString();
    }

    @Override
    public String countTotalDiscount(List<GoodsDetail> resultZS) {
        BigDecimal dist = new BigDecimal(0);
        // 更新 （调整后需要更新）
        for (int j = 0; j < resultZS.size(); j++) {
            GoodsDetail goodsDetail = resultZS.get(j);
            //调整后的折扣金额 可能会变 需要更新
            BigDecimal disMon = new BigDecimal(goodsDetail.getDisMon());
            //四色五入防止溢出
            disMon.setScale(2, BigDecimal.ROUND_HALF_UP);
            //折扣金额 再次累加求和
            dist = dist.add(disMon);
        }
        return dist.toString();
    }

    /**
     * 针对折扣金额进行调整
     * @param goodsList
     * @param disTotal
     * @return
     */
    private GoodsList amendment(GoodsList goodsList, double disTotal) {
        int realCount = 0;
        for(GoodsDetail fss : goodsList.getResultZS()){
            if(!fss.isO()){
                realCount++;//真实非0数据
            }
        }
        //折扣总金额
        BigDecimal dt = BigDecimal.valueOf(Math.abs(goodsList.getDisTotal()));
        //四舍5入 防止溢出
        BigDecimal b1 = MathUtil.getTwoPointBig(dt);
        //实际的折扣金额数
        BigDecimal b2 = new BigDecimal(Double.toString(disTotal));
        //折扣金额总误差
        BigDecimal b3 = b1.subtract(b2);
        double wc = b3.doubleValue();
        if (wc == 0) {
            return goodsList;
        } else {
            int intwc ;
            boolean flag = false;
            if (wc < 0) {
                double f = Math.floor(wc * 100);
                if (f >= wc * 100) {
                    intwc = (int) f;
                } else {
                    intwc = (int) f + 1;
                }
            } else {
                flag = true;
                intwc = (int) Math.floor(wc * 100);
            }
            intwc = Math.abs(intwc);
            List<GoodsDetail> list = goodsList.getResultZS();
            int count = Math.abs(intwc % realCount);
            int countzs = Math.abs(intwc / realCount);
            double disMon;
            int index = -1;
            for (int i = 0; i < list.size(); i++) {
                GoodsDetail fsg = list.get(i);
                if(fsg.isO()){
                    continue;
                }
                index++;
                disMon = Double.parseDouble(fsg.getDisMon());
                if (!flag) {
                    if (index < count){
                        fsg.setDisMon((disMon - countzs * 0.01 - 0.01) + "");
                    }
                    else {
                        fsg.setDisMon((disMon - countzs * 0.01) + "");
                    }
                } else {
                    if (index < count) {
                        fsg.setDisMon((disMon + countzs * 0.01 + 0.01) + "");
                    }
                    else {
                        fsg.setDisMon((disMon + countzs * 0.01) + "");
                    }
                }
            }
            goodsList.setResultZS(list);
        }
        return goodsList;
    }

    /**
     * 计算商品退货总金额
     * @param list 商品列表
     * @return 商品退货总金额
     */
    private BigDecimal getTotalZk(List<GoodsDetail> list) {
        BigDecimal b = new BigDecimal(0);
        for (GoodsDetail fsg : list) {
            BigDecimal b1 = new BigDecimal(fsg.getDisMon());
            b1 = MathUtil.getTwoPointBig(b1);
            b = b1.add(b);
        }
        return b;
    }

    /**
     * 计算商品不含税总金额
     * @param list 商品列表
     * @return 商品不含税总金额
     */
    private BigDecimal getTotalNoRateMon(List<GoodsDetail> list) {
        BigDecimal b = new BigDecimal(0);
        for (GoodsDetail fsg : list) {
            BigDecimal b1 = new BigDecimal(fsg.getNoRateMon());
            b1 = MathUtil.getTwoPointBig(b1);
            b = b1.add(b);
        }
        return b;
    }

    /**
     * 计算商品总金额
     * @param list 商品列表
     * @return 商品总金额
     */
    private BigDecimal getTotalMon(List<GoodsDetail> list) {
        BigDecimal b = new BigDecimal(0);
        for (GoodsDetail fsg : list) {
            BigDecimal b1 = new BigDecimal(fsg.getMon());
            b1 = MathUtil.getTwoPointBig(b1);
            b = b1.add(b);
        }
        return b;
    }

    /**
     * 根据每一行解析商品
     * @param line 文字读取行
     * @return 商品GoodsDetail
     */
    private GoodsDetail changeGoodsList(String line) {
        GoodsDetail fsg = new GoodsDetail();
        String[] msg = line.split("~~");
        //商品名称
        fsg.setName(msg[1]);
        //根据商品名称匹配税收分类编码
        fsg.setSsflbm("106010504");
        //商品单位
        fsg.setDw(msg[2]);
        //商品规格
        fsg.setType(msg[3]);
        //商品数量
        fsg.setNum(msg[4]);
        //商品金额
        fsg.setMon(String.format("%.2f", Double.parseDouble(msg[5])));
        if (msg[6] == null || msg[6].trim().length() == 0) {
            msg[6] = "0";
        }
        //不含税金额
        fsg.setNoRateMon(msg[6]);
        //税额
        fsg.setRate(msg[7]);
        //折扣金额
        if (msg[8] == null || msg[8].trim().length() == 0) {
            msg[8] = "0";
        }
        fsg.setDisMon(String.format("%.2f", Double.parseDouble(msg[8])));
        fsg.setMsg(msg);
        return fsg;
    }
}
